﻿using System.Diagnostics;

namespace DimensionsHelper.LanguageService.Syntax;

public class PreIfStatement : PreNodeList
{
    private readonly SourceNode _preIfKeywordToken;
    private PreExpression? _conditionExpression;
    private PreIfStatement? _elseBranch;

    internal PreIfStatement(SourceNode? parent, SourceNode preIfKeywordToken) :
        base(parent, SyntaxKinds.PreIfStatement)
    {
        SetChildField(ref _preIfKeywordToken, preIfKeywordToken);
    }

    public override bool IsParserSkipped => true;


    /// <summary>
    ///     #if 关键字
    /// </summary>
    public SourceNode PreIfKeywordToken => _preIfKeywordToken;

    /// <summary>
    ///     #if指令的条件语句
    /// </summary>
    public PreExpression? ConditionExpression => _conditionExpression;


    /// <summary>
    ///     如果此 #if 语句的条件语句判定通过，设置此属性为true。
    /// </summary>
    public bool Succeed { get; set; } = false;


    /// <summary>
    ///     如果语句是 #ifdef 语句，返回<see langword="true" />
    /// </summary>
    public bool IsIfDef => _preIfKeywordToken.IsNode(SyntaxKinds.PreIfDefKeywordToken);


    /// <summary>
    ///     如果语句是 #ifndef 语句，返回<see langword="true" />
    /// </summary>
    public bool IsIfNDef => _preIfKeywordToken.IsNode(SyntaxKinds.PreIfNDefKeywordToken);


    /// <summary>
    ///     后续的 #else 或 #elif 表达式
    /// </summary>
    public PreIfStatement? ElseBranch => _elseBranch;


    /// <summary>
    ///     更新 #if 语句的条件表达式。
    /// </summary>
    /// <param name="conditionExpression">条件表达式节点</param>
    public PreIfStatement Update(PreExpression conditionExpression)
    {
        Debug.Assert(_preIfKeywordToken.IsOneOfNode(SyntaxKinds.PreIfKeywordToken,
            SyntaxKinds.PreElIfKeywordToken));
        SetChildNullableField(ref _conditionExpression, PreEmptyExpression.IsNullOrDefaultEmptyExpression,
            conditionExpression);
        return this;
    }


    /// <summary>
    ///     更新 #ifdef / #ifndef 语句的宏名。同时，如果 #if 的条件语句只有一个标识符时，也可以使用此方法更新<see cref="ConditionExpression" />。
    /// </summary>
    /// <param name="macroNameIdentifier">宏名称节点或表达式</param>
    public PreIfStatement Update(SourceIdentifier macroNameIdentifier)
    {
        SetChildNullableField(ref _conditionExpression, PreEmptyExpression.IsNullOrDefaultEmptyExpression,
            macroNameIdentifier);
        return this;
    }


    /// <summary>
    ///     更新分支语句块。
    /// </summary>
    /// <remarks>
    ///     只有 #if 语句块才支持分支语句，#ifdef 和 #ifndef 只能有自身的语句块。
    /// </remarks>
    /// <param name="elseBranch">分支语句块</param>
    public PreIfStatement Update(PreIfStatement elseBranch)
    {
        Debug.Assert(PreIfKeywordToken.IsOneOfNode(SyntaxKinds.PreIfKeywordToken, SyntaxKinds.PreElIfKeywordToken));
        SetChildNullableField(ref _elseBranch, elseBranch);
        return this;
    }


    public override void AcceptVisitor<T>(SyntaxNodeVisitor<T> visitor)
    {
        Accept(visitor, ConditionExpression);
        AcceptList(visitor, NodeListInternal);
        Accept(visitor, ElseBranch);
    }
}


public static partial class NodeFactory
{
    /// <summary>
    ///     创建 #if 语句块。
    /// </summary>
    /// <param name="parent">父节点</param>
    /// <param name="preIfKeywordToken">#if 关键字</param>
    /// <param name="conditionExpression">#if 后的条件表达式</param>
    /// <param name="nodes">语句块内的节点列表</param>
    public static PreIfStatement CreatePreIfStatement(SourceNode? parent, SourceNode preIfKeywordToken,
        PreExpression? conditionExpression, IEnumerable<SourceNode>? nodes)
    {
        Debug.Assert(preIfKeywordToken.IsOneOfNode(SyntaxKinds.PreIfKeywordToken, SyntaxKinds.PreElIfKeywordToken,
            SyntaxKinds.PreElseKeywordToken));
        Debug.Assert(conditionExpression == null ||
                     !PreEmptyExpression.IsNullOrDefaultEmptyExpression(conditionExpression));
        PreIfStatement stat = new(parent, preIfKeywordToken);
        if (!PreEmptyExpression.IsNullOrDefaultEmptyExpression(conditionExpression))
        {
            stat.Update(conditionExpression);
        }

        if (nodes != null)
        {
            stat.AddNodes(nodes);
        }

        return stat;
    }


    /// <summary>
    ///     创建 #ifdef 或 #ifndef 语句节点。
    /// </summary>
    /// <param name="parent">父节点</param>
    /// <param name="preIfDefOrNDefKeywordToken">#ifdef 或 #ifndef 关键字节点</param>
    /// <param name="macroNameIdentifier">宏名</param>
    /// <param name="nodes">语句块内的节点列表</param>
    public static PreIfStatement CreatePreIfDefOrNDefStatement(SourceNode? parent,
        SourceNode preIfDefOrNDefKeywordToken, SourceIdentifier? macroNameIdentifier,
        IEnumerable<SourceNode>? nodes)
    {
        Debug.Assert(preIfDefOrNDefKeywordToken.IsOneOfNode(SyntaxKinds.PreIfDefKeywordToken,
            SyntaxKinds.PreIfNDefKeywordToken));
        Debug.Assert(
            macroNameIdentifier == null || !SourceIdentifier.IsNullOrDefaultIdentifier(macroNameIdentifier));
        PreIfStatement stat = new(parent, preIfDefOrNDefKeywordToken);
        if (!SourceIdentifier.IsNullOrDefaultIdentifier(macroNameIdentifier))
        {
            stat.Update(macroNameIdentifier);
        }

        // 添加节点
        if (nodes != null)
        {
            stat.AddNodes(nodes);
        }

        return stat;
    }
}